import React, { memo } from 'react';
import { Spin } from 'antd';
import { LoadingOutlined } from '@ant-design/icons';
import classNames from 'classnames';
import styles from './Loading.module.css';

/**
 * 加载组件属性接口
 * @description 定义加载组件的属性
 */
export interface ILoadingProps {
  /** 是否显示加载状态 */
  loading?: boolean;
  /** 加载提示文本 */
  tip?: string;
  /** 加载组件尺寸 */
  size?: 'small' | 'default' | 'large';
  /** 加载组件类型 */
  type?: 'spin' | 'dots' | 'pulse' | 'skeleton';
  /** 是否延迟显示加载状态（毫秒） */
  delay?: number;
  /** 自定义加载指示器 */
  indicator?: React.ReactElement;
  /** 是否作为包装器使用 */
  wrapper?: boolean;
  /** 包装器最小高度 */
  minHeight?: number | string;
  /** 自定义类名 */
  className?: string;
  /** 自定义样式 */
  style?: React.CSSProperties;
  /** 子元素 */
  children?: React.ReactNode;
}

/**
 * 加载组件
 * @description 提供多种样式的加载指示器，支持包装器模式和独立使用
 */
const Loading = memo<ILoadingProps>(({
  loading = true,
  tip,
  size = 'default',
  type = 'spin',
  delay = 0,
  indicator,
  wrapper = false,
  minHeight,
  className,
  style,
  children
}) => {
  // 获取自定义指示器
  const getIndicator = () => {
    if (indicator) {
      return indicator;
    }

    switch (type) {
      case 'spin':
        return <LoadingOutlined style={{ fontSize: getSizeValue() }} spin />;
      case 'dots':
        return (
          <div className={styles.dotsIndicator}>
            <span className={styles.dot} />
            <span className={styles.dot} />
            <span className={styles.dot} />
          </div>
        );
      case 'pulse':
        return <div className={styles.pulseIndicator} />;
      case 'skeleton':
        return (
          <div className={styles.skeletonIndicator}>
            <div className={styles.skeletonLine} />
            <div className={styles.skeletonLine} />
            <div className={styles.skeletonLine} />
          </div>
        );
      default:
        return <LoadingOutlined style={{ fontSize: getSizeValue() }} spin />;
    }
  };

  // 获取尺寸对应的数值
  const getSizeValue = () => {
    switch (size) {
      case 'small':
        return 14;
      case 'large':
        return 32;
      case 'default':
      default:
        return 24;
    }
  };

  // 组合类名
  const loadingClassName = classNames(
    styles.loading,
    {
      [styles.small]: size === 'small',
      [styles.large]: size === 'large',
      [styles.wrapper]: wrapper,
      [styles.standalone]: !wrapper,
    },
    className
  );

  // 组合样式
  const loadingStyle: React.CSSProperties = {
    minHeight: wrapper && minHeight ? minHeight : undefined,
    ...style
  };

  // 如果是包装器模式
  if (wrapper) {
    return (
      <Spin
        spinning={loading}
        tip={tip}
        size={size}
        indicator={getIndicator()}
        delay={delay}
        className={loadingClassName}
        style={loadingStyle}
      >
        <div className={styles.content}>
          {children}
        </div>
      </Spin>
    );
  }

  // 如果不需要显示加载状态，直接返回子元素
  if (!loading) {
    return <>{children}</>;
  }

  // 独立使用模式
  return (
    <div className={loadingClassName} style={loadingStyle}>
      <Spin
        spinning={loading}
        size={size}
        indicator={getIndicator()}
        delay={delay}
      />
      {tip && (
        <div className={styles.tipText}>
          {tip}
        </div>
      )}
    </div>
  );
});

Loading.displayName = 'Loading';

export default Loading;